﻿using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System;


namespace ThePresenter.Windows.Data
{
	public class Shape : INotifyPropertyChanged
	{
		#region Fields
		StrokeCollection _Strokes;

		string _Name;
		#endregion


		#region Properties
		/// <summary>
		/// Gets or sets the strokes.
		/// </summary>
		/// <value>The strokes.</value>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		public StrokeCollection Strokes
		{
			get
			{
				return _Strokes;
			}
			protected set
			{
				_Strokes = value;
				OnPropertyChanged("Strokes");
			}
		}

		/// <summary>
		/// Gets or sets the strokes data.
		/// </summary>
		/// <value>The strokes data.</value>
		public string StrokesData
		{
			get
			{
				using (var ms = new MemoryStream())
				{
					Strokes.Save(ms, true);

					//return BitConverter.ToString(ms.ToArray());
					return Convert.ToBase64String(ms.ToArray());
				}
			}
			set
			{
				if (!string.IsNullOrEmpty(value))
				{
					var bytes = Convert.FromBase64String(value) as byte[];

					using (var ms = new MemoryStream(bytes))
					{
						ms.Position = 0;

						Strokes = new StrokeCollection(ms);
					}
				}
			}
		}

		/// <summary>
		/// Gets or sets the name.
		/// </summary>
		/// <value>The name.</value>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		public string Name
		{
			get
			{
				return _Name;
			}
			set
			{
				if (_Name != value)
				{
					_Name = value;
					OnPropertyChanged("Name");
				}
			}
		}
		#endregion


		#region Constructors
		/// <summary>
		/// Initializes a new instance of the <see cref="Shape"/> class.
		/// </summary>
		public Shape()
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Shape"/> class.
		/// </summary>
		/// <param name="strokes">The strokes.</param>
		/// <param name="name">The name.</param>
		public Shape(StrokeCollection strokes, string name)
			: this()
		{
			Matrix m = Matrix.Identity;

			Rect r = strokes.GetBounds();
			m.Translate(-r.X, -r.Y);

			this.Strokes = strokes.Clone();
			this.Strokes.Transform(m, false);

			this.Name = name;
		}
		#endregion


		#region Methods
		/// <summary>
		/// Raises the <see cref="E:PropertyChanged"/> event.
		/// </summary>
		/// <param name="propertyName">The name of the property.</param>
		protected void OnPropertyChanged(string propertyName)
		{
			if (PropertyChanged != null)
				PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
		}

		/// <summary>
		/// Gets the thumbnail.
		/// </summary>
		/// <param name="shape">The shape.</param>
		/// <param name="targetSize">Size of the target.</param>
		/// <returns>New instance of ImageSource.</returns>
		public static ImageSource GetThumbnail(Shape shape, Size targetSize)
		{
			return GetThumbnail(shape.Strokes, targetSize);
		}

		/// <summary>
		/// Gets the thumbnail.
		/// </summary>
		/// <param name="strokes">The strokes.</param>
		/// <param name="targetSize">Size of the target.</param>
		/// <returns>New instance of ImageSource.</returns>
		public static ImageSource GetThumbnail(StrokeCollection strokes, Size targetSize)
		{
			if (strokes == null || strokes.Count == 0)
				return null;

			Rect sourceRect = strokes.GetBounds();
			Size sourceSize = sourceRect.Size; // velkost tvaru
			Size thumbSize = targetSize;

			// vyriesit pomer stran
			if (sourceSize.Width / sourceSize.Height <= targetSize.Width / targetSize.Height) // vyssi alebo rovny ako thumb
			{
				double HeightRatio = targetSize.Height / sourceSize.Height;
				thumbSize.Width = HeightRatio * sourceSize.Width;
			}
			else // sirsi ako thumb
			{
				double WidthRatio = targetSize.Width / sourceSize.Width;
				thumbSize.Height = WidthRatio * sourceSize.Height;
			}

			Matrix m = Matrix.Identity;
			m.Translate(-sourceRect.X, -sourceRect.Y);
			m.Scale(thumbSize.Width / sourceSize.Width, thumbSize.Height / sourceSize.Height);

			StrokeCollection thumb_strokes = strokes.Clone();
			thumb_strokes.Transform(m, true);

			var dpi = new System.Drawing.PointF(96, 96);
			InkCanvas c = new InkCanvas() { Strokes = thumb_strokes, Width = thumbSize.Width, Height = thumbSize.Height };

			RenderTargetBitmap bitmap = new RenderTargetBitmap((int)Math.Ceiling(thumbSize.Width), (int)Math.Ceiling(thumbSize.Height), dpi.X, dpi.Y, PixelFormats.Pbgra32);
			bitmap.Render(c);

			PngBitmapEncoder image = new PngBitmapEncoder();
			image.Frames.Add(BitmapFrame.Create(bitmap));

			var ms = new MemoryStream();
			image.Save(ms);
			ms.Position = 0;

			return Helpers.GetBitmapImageFromStream(ms);
		}
		#endregion


		#region INotifyPropertyChanged Members
		/// <summary>
		/// Occurs when a property value changes.
		/// </summary>
		public event PropertyChangedEventHandler PropertyChanged;
		#endregion
	}
}
